package com.witmore.skyline.web.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.witmore.skyline.db.entity.CameraDO;
import com.witmore.skyline.db.entity.CameraTaskDO;
import com.witmore.skyline.db.mapper.CameraMapper;
import com.witmore.skyline.db.mapper.CameraTaskMapper;
import com.witmore.skyline.web.controller.enums.CameraPicSourceTypeEnum;
import com.witmore.skyline.web.service.CameraCaptureTpService;
import com.witmore.skyline.web.service.CameraService;
import com.witmore.skyline.web.service.third.constants.ApiClientCommonConstant;
import com.witmore.skyline.web.service.third.tplink.ApiCaptureUrlClient;
import com.witmore.skyline.web.service.third.tplink.TaskWorker;
import com.witmore.skyline.web.service.third.tplink.dto.TpFileResultDTO;
import com.witmore.skyline.web.service.third.tplink.dto.TpResultDTO;
import com.witmore.skyline.web.service.third.tplink.dto.TpResultDataDTO;
import com.witmore.skyline.web.service.third.tplink.dto.TpThreadTaskQueueDTO;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;

import static java.lang.String.format;

/**
 * Description: CameraCaptureTpServiceImpl
 * Author: 豆子高
 * Date: 2025/3/17 13:33
 */
@Slf4j
@Service
public class CameraCaptureTpServiceImpl implements CameraCaptureTpService {

    @Autowired
    private CameraMapper cameraMapper;
    @Autowired
    private CameraService cameraService;
    @Autowired
    private CameraTaskMapper cameraTaskMapper;
    @Autowired
    private TaskWorker taskWorker;

    /**
     * QPS限制，默认5
     */
    @Getter
    @Value("${aliyun.viapi.pedestrian.qps:5}")
    private int qpsLimit;


    @Override
    public String submitCaptureTaskTP(CameraDO cameraDO) {
        try {
            // 创建抓取图片任务
            TpResultDTO resultDTO = ApiCaptureUrlClient.submitCaptureImageTask(cameraDO.getCameraSn());
            if (resultDTO == null || resultDTO.getError_code() != 0 || StringUtils.isEmpty(resultDTO.getResult())) {
                log.error("调用创建抓取图片任务接口失败 error cameraSn-->{},msg-->{}",
                        cameraDO.getCameraSn(), resultDTO == null ? "TpResultDTO为空" : JSONObject.toJSONString(resultDTO));
                return null;
            }
            TpResultDataDTO tpResultDataDTO = JSONObject.parseObject(resultDTO.getResult(), TpResultDataDTO.class);
            return tpResultDataDTO.getTaskId();
        } catch (Exception e) {
            log.error("创建抓取图片任务失败 error cameraSn-->{},msg-->{}, e",
                    cameraDO.getCameraSn(), e.getMessage(), e);
        }
        return null;
    }

    @Override
    public TpResultDataDTO executeCapturePicTaskStatus(String taskId) {
        // 获取抓取图片任务状态
        TpResultDTO resultDTO = ApiCaptureUrlClient.getTaskInfo(taskId);
        if (resultDTO == null || resultDTO.getError_code() != 0 || StringUtils.isEmpty(resultDTO.getResult())) {
            log.error("getCaptureUrlTaskStatus error taskId-->{},msg-->{}",
                    taskId, resultDTO == null ? "TpResultDTO为空" : JSONObject.toJSONString(resultDTO));
            return null;
        }
        return JSONObject.parseObject(resultDTO.getResult(), TpResultDataDTO.class);
    }


    @Override
    public String getCameraCaptureFile(TpThreadTaskQueueDTO queueDTO) {
        // 获取抓取图片任务文件
        String getUrl = this.taskSuccessGetUrl(queueDTO.getTaskId());
        String fileName = format(ApiClientCommonConstant.OSS_FILE_UPLOAD_TP_PREFIX, queueDTO.getCameraSn())
                + queueDTO.getTaskId() + "_" + System.currentTimeMillis()
                + ".jpg";
        String ossUrl = cameraService.convertOssUrl(fileName, getUrl);
        CameraDO cameraDO = cameraMapper.selectById(queueDTO.getSkylineCameraId());
        cameraService.saveCameraPic(cameraDO, ossUrl, CameraPicSourceTypeEnum.getEnumByCode(queueDTO.getSourceType()));
        return ossUrl;
    }


    @Override
    public String tpCameraCapturePicHandler(CameraDO cameraDO, CameraTaskDO cameraTaskDO) {
        String taskId = this.submitCaptureTaskTP(cameraDO);
        if (StringUtils.isEmpty(taskId)) {
            return null;
        }
        cameraTaskDO.setTaskId(taskId);
        cameraTaskMapper.insert(cameraTaskDO);
        // 任务入队列
        TpThreadTaskQueueDTO tpThreadTaskQueueDTO = new TpThreadTaskQueueDTO();
        tpThreadTaskQueueDTO.setTaskId(taskId);
        tpThreadTaskQueueDTO.setSkylineCameraId(cameraDO.getId());
        tpThreadTaskQueueDTO.setCameraSn(cameraDO.getCameraSn());
        tpThreadTaskQueueDTO.setOrgId(cameraDO.getOrgId());
        tpThreadTaskQueueDTO.setSourceType(CameraPicSourceTypeEnum.USER_CAPTURE_IMAGE_CLOUD.getCode());
        taskWorker.run(tpThreadTaskQueueDTO);
        return taskId;
    }


    @Override
    public void saveCaptureRecord(TpThreadTaskQueueDTO tpThreadTaskQueueDTO, TpResultDataDTO tpResultDataDTO, String ossUrl) {
        CameraTaskDO cameraTaskDO = cameraTaskMapper.selectOne(new LambdaQueryWrapper<CameraTaskDO>()
                .eq(CameraTaskDO::getTaskId, tpThreadTaskQueueDTO.getTaskId())
                .eq(CameraTaskDO::getOrgId, tpThreadTaskQueueDTO.getOrgId())
                .eq(CameraTaskDO::getCameraSn, tpThreadTaskQueueDTO.getCameraSn())
        );
        if (cameraTaskDO == null) {
            return;
        }
        //更新 状态
        cameraTaskMapper.updateById(CameraTaskDO.builder()
                .id(cameraTaskDO.getId())
                .errorCode(tpResultDataDTO.getError_code())
                .errorMsg(tpResultDataDTO.getErrorMsg())
                .updateTime(LocalDateTime.now())
                .url(ossUrl)
                .build());
    }

    @Override
    public void executeSubmitCapturePicTaskTP(String cameraSn) {
        int page = 1;
        int pageSize = qpsLimit;
        while (true) {
            log.info("TP-Link 抓取图片任务开始执行 page-->{},pageSize-->{}", page, pageSize);
            Page<CameraDO> cameraDOPage = cameraMapper.selectPage(new Page<>(page, pageSize), new LambdaQueryWrapper<CameraDO>()
                    .eq(CameraDO::getIsDeleted, 0)
                    .in(StringUtils.isNotEmpty(cameraSn), CameraDO::getCameraSn, cameraSn)
                    .eq(CameraDO::getCameraStatus, 1)
                    .eq(CameraDO::getType, 2));
            if (cameraDOPage == null || CollectionUtils.isEmpty(cameraDOPage.getRecords())) {
                return;
            }
            cameraDOPage.getRecords().forEach(cameraDO -> {
                try {
                    String taskId = this.submitCaptureTaskTP(cameraDO);
                    // 任务入队列
                    TpThreadTaskQueueDTO tpThreadTaskQueueDTO = new TpThreadTaskQueueDTO();
                    tpThreadTaskQueueDTO.setTaskId(taskId);
                    tpThreadTaskQueueDTO.setSkylineCameraId(cameraDO.getId());
                    tpThreadTaskQueueDTO.setCameraSn(cameraDO.getCameraSn());
                    tpThreadTaskQueueDTO.setOrgId(cameraDO.getOrgId());
                    tpThreadTaskQueueDTO.setSourceType(CameraPicSourceTypeEnum.SCHEDULED_TASK.getCode());
                    taskWorker.run(tpThreadTaskQueueDTO);
                } catch (Exception e) {
                    log.warn("TP-Link 创建抓取图片任务失败 error cameraSn-->{},msg-->{}, e",
                            cameraDO.getCameraSn(), e.getMessage(), e);
                }

            });

            // 为人体检测QPS只有5 做限制 TODO 后续优化
            try {
                log.info("TP-Link 创建抓取图片任务间隔1秒");
                Thread.sleep(1000);
            } catch (Exception e) {
                log.error("TP-Link 创建抓取图片任务间隔1秒 error", e);
            }

            page++;
        }
    }


    private String taskSuccessGetUrl(String taskId) {
        TpResultDTO resultDTO = ApiCaptureUrlClient.getTaskFilePage(taskId);
        if (resultDTO == null || resultDTO.getError_code() != 0 || StringUtils.isEmpty(resultDTO.getResult())) {
            log.error("调用获取抓取图片任务状态接口失败 error taskId-->{},msg-->{}",
                    taskId, resultDTO == null ? "TpResultDTO为空" : JSONObject.toJSONString(resultDTO));
            return null;
        }
        JSONObject jsonObject = JSONObject.parseObject(resultDTO.getResult());
        Integer total = (Integer) jsonObject.get("total");
        if (total == null || total == 0) {
            return null;
        }
        JSONArray jsonArray = (JSONArray) jsonObject.get("list");
        // TODO 待验证
        TpFileResultDTO tpFileResultDTO = JSONObject.parseObject(jsonArray.get(0).toString(), TpFileResultDTO.class);
        return tpFileResultDTO.getUrls()[0];
    }


}
